package com.blockmeta.bbs.businesslibrary.launch;


import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Base64;
import android.util.Log;

import com.blankj.utilcode.util.LogUtils;

import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.StringUtils;
import com.blockmeta.bbs.baselibrary.base.app.BaseApp;
import com.blockmeta.bbs.baselibrary.net.callback.MyStringCallback;
import com.blockmeta.bbs.baselibrary.provider.IApplicationProvider;
import com.blockmeta.bbs.baselibrary.utils.SecurityUtil;
import com.blockmeta.bbs.baselibrary.utils.SharedPreferenceUtil;
import com.blockmeta.bbs.baselibrary.utils.gson.GsonUtil;
import com.blockmeta.bbs.businesslibrary.arouter.RouterHelper;
import com.blockmeta.bbs.businesslibrary.arouter.RouterPath;
import com.blockmeta.bbs.businesslibrary.constant.Constant;
import com.blockmeta.bbs.businesslibrary.constant.NetConstant;
import com.blockmeta.bbs.businesslibrary.flutter.MethodChannelFlutterPlugins;
import com.blockmeta.bbs.businesslibrary.net.pojo.UserToken;
import com.blockmeta.bbs.businesslibrary.util.AccountHelper;
import com.blockmeta.bbs.businesslibrary.util.AppCode;
import com.blockmeta.bbs.businesslibrary.util.GateWayUtil;
import com.blockmeta.bbs.businesslibrary.util.JWTRefreshUtil;
import com.blockmeta.bbs.businesslibrary.util.ReportIssue;
import com.google.gson.Gson;
import com.hellobike.flutter.thrio.navigator.EngineReadyListener;
import com.hellobike.flutter.thrio.navigator.FlutterEngineFactory;
import com.zhy.http.okhttp.OkHttpUtils;

import org.greenrobot.eventbus.EventBus;
import org.jetbrains.annotations.Nullable;

import java.lang.ref.WeakReference;
import java.util.HashMap;

import okhttp3.Call;
import okhttp3.MediaType;

import static com.zhy.http.okhttp.builder.OkHttpRequestBuilder.USER_AGENT;


public class ResourceDownload extends Thread {

    public enum WorkStatus {
        INIT,
        ING,        // 處理中
        LOCAL_OK,    // local bundle載入完成
        OK,            // server bundle載入成功
        OOS,        // 暫停服務(Out Of Service)
        FAIL        // 失敗
    }

    protected EventBus m_eventBus;
    protected WorkStatus m_status;
    protected String m_strUrl;
    protected String m_Ver;
    protected DownloadInfo m_info;
    protected int m_nRetryInterval = 1; // getBundle失敗的重試秒數 2^m_nRetryInterval, exponential backoff
    protected boolean m_bRetry = true;  // getBundle失敗 是否retry
    protected static Handler m_hHandler;
    protected boolean m_bRun = false;
    protected WeakReference<Context> mContext;
    protected String mAndroidId;

    public static final int MSG_GET_BUNDLE = 6454111;
    public static final int MSG_GET_PUBLICKEY = 6454321;
    public static final int MSG_REFRESHJWT = 6454421;
    public static final int MSG_CONFIRM_CHANNEL_OK = 6454621;
    private static final int RETRY_TIME_LIMIT = 3;  // 2^1 ~ 2^8

    public ResourceDownload(Context context, String androidId) {
        mContext = new WeakReference<Context>(context);
        mAndroidId = androidId;
        m_eventBus = new EventBus();
        m_status = WorkStatus.INIT;
        m_Ver = SecurityUtil.getVersionName(BaseApp.getApp());
        m_info = new DownloadInfo(m_Ver);

        m_hHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case MSG_GET_BUNDLE:
                        getBundle();
                        break;
                    case MSG_GET_PUBLICKEY:
                        GateWayUtil.getPublicKey(mContext.get(), m_hHandler);
                        break;
//                    case MSG_REFRESHJWT:
//                        JWTRefreshUtil.refreshJWT(mContext.get(), m_hHandler);
//                        break;
                    case MSG_CONFIRM_CHANNEL_OK:
                        MethodChannelFlutterPlugins.send("ready","");
                        break;
                }
                super.handleMessage(msg);
            }
        };
    }



    public EventBus getEventBus() {
        return m_eventBus;
    }

    public void onPause() {
        m_bRetry = false;
        if (m_hHandler != null) {
            m_hHandler.removeCallbacksAndMessages(null);
        }
    }

    public void onResume() {
        m_bRetry = true;
        m_nRetryInterval = 1;

        if (m_status == WorkStatus.FAIL) {
            getBundle();
        }
    }

    @Override
    public void run() {
        if (!m_bRun) {
            m_bRun = true;

            sendEvent(WorkStatus.ING);
            while (FlutterEngineFactory.INSTANCE.getEngine("main") == null){
                try {
                    Log.d("flutterting", "init flutter nook");
                    sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            while (!MethodChannelFlutterPlugins.isReady){
                try {
                    m_hHandler.sendEmptyMessage(MSG_CONFIRM_CHANNEL_OK);
                    Log.d("flutterting", "wait ready");
                    sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            m_hHandler.sendEmptyMessage(MSG_GET_PUBLICKEY);

            m_info.loadLocal();
//            Looper.myLooper();
            sendEvent(WorkStatus.LOCAL_OK);

//            Looper.prepare();
//            try {
//                if (SharedPreferenceUtil.getString(mContext.get(), Constant.GETUI_TOKEN, null) == null) {
//                    sleep(3000);
//                }
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            Looper.loop();
        }
    }

    protected void sendEvent(WorkStatus status) {
        m_status = status;
        m_eventBus.post(new Event_DownloadStatus(status));
    }

    protected void getBundle() {
        String GETUI_TOKEN = SharedPreferenceUtil.getString(mContext.get(), Constant.GETUI_TOKEN, null);
        final String version = SecurityUtil.getVersionName(BaseApp.getApp());
        LogUtils.d("author" + "getBundle: " + version);
        final HashMap<String, String> map = new HashMap<>();
        map.put("deviceid", mAndroidId);
        map.put("version", version);
        map.put("imei", AccountHelper.id(BaseApp.getApp()));
        if (GETUI_TOKEN != null) map.put("cid", GETUI_TOKEN);
        OkHttpUtils.postString()
                .addHeader(USER_AGENT, "quhui")
                .addHeader("app_code", "quhui")
                //.addHeader("token",MyApplication.getApp().getToken())
                .mediaType(MediaType.parse("application/json; charset=utf-8"))
                .content(new Gson().toJson(map))
                .url(NetConstant.USER_INIT)
                .build()
                .execute(new MyStringCallback() {
                    @Override
                    public void onError(Call call, Exception e, int id) {
                        if (m_nRetryInterval < RETRY_TIME_LIMIT) {
                            long time = (long) (Math.pow(2, m_nRetryInterval) * 1000);
                            try {
                                Thread.sleep(time);
                                if (m_bRetry) {
                                    m_hHandler.sendEmptyMessage(MSG_GET_BUNDLE);
                                }
                            } catch (InterruptedException ex) {
                                ex.printStackTrace();
                            }
                            m_nRetryInterval++;
                        } else {
                            sendEvent(WorkStatus.FAIL);
                        }
                    }

                    @Override
                    public void onResponse(String response, int id) {
                        try {
                            //需要在这里进行自己的Cookie的持久化处理
                            String version = SharedPreferenceUtil.getString(BaseApp.getApp(), Constant.APP_VERSION, null);
                            LogUtils.d("author" + "onResponse: " + response);
                            UserToken userToken = GsonUtil.buildGson().fromJson(response, UserToken.class);
                            if(userToken == null || StringUtils.isEmpty(userToken.getConfig_url())){
                                throw new Exception("init request fail");
                            }
                            MethodChannelFlutterPlugins.send("appversion", response);
                            if (version != null && version.equals(userToken.getLast_version())) {
                                SharedPreferenceUtil.putBoolean(BaseApp.getApp(), Constant.NO_NOTICE_UPDATE, true);
                            } else {
                                SharedPreferenceUtil.putBoolean(BaseApp.getApp(), Constant.NO_NOTICE_UPDATE, false);
                            }
                            SharedPreferenceUtil.putString(BaseApp.getApp(), Constant.BUNDLEURL, userToken.getConfig_url());
                            SharedPreferenceUtil.putString(BaseApp.getApp(), Constant.APP_VERSION, userToken.getLast_version());
                            SharedPreferenceUtil.putBoolean(BaseApp.getApp(), Constant.ISFORCE, userToken.isForce_update());
                            SharedPreferenceUtil.putString(BaseApp.getApp(), Constant.UPDATE_URL, userToken.getUrl());
                            SharedPreferenceUtil.putString(BaseApp.getApp(), Constant.UPDATE_DES, userToken.getInfo());


                            SharedPreferenceUtil.putString(BaseApp.getApp(), Constant.BANNER_FLASH, new Gson().toJson(userToken.getFlash()));
                            m_info.loadServer(userToken.getConfig_url(), new DownloadInfo.BundleParseCallback() {
                                @Override
                                public void onSuccess() {
                                    sendEvent(WorkStatus.OK);
                                }

                                @Override
                                public void onError() {
                                }
                            });
                        } catch (Exception e) {
                            LogUtils.d("author" + "exception: " + e.getMessage());
                        }
                    }
                });
    }


    public static class Event_DownloadStatus {
        public WorkStatus m_status;

        Event_DownloadStatus(WorkStatus status) {
            m_status = status;
        }
    }


}
